import os, sys, time
from threading import Lock

from ivic.core import Logging
from ivic.vprocess.Vprocess import *
from ivic.vprocess.PathUtils import *

logger = Logging.get_logger('ivic.vprocess.Server')

#def mapUserPath(user, args):
#    newpath = ""
#    
#    if args and args != "":
#        if user == "root":
#            newpath = "/root/" + args
#        else:
#            newpath = "/home/" + user + "/" + args
#        
#    return newpath

#****************vprocess server class********************#
class VProcessServer:
    
    def __init__(self, config=None):
#        self.vserver = config["xxxx"]
        try:
            if config == None:
                self.config = VProcessConfig()
            else: self.config = config
            
            self.userproc = {}
            self.procmap = {}
            self.synclock = Lock()
            self.sermon = None
            
        except Exception, e:
          logger.error('%s' % e)  
        
    def createVProcess(self, user, software, display, args=""):
        try:
            newpath = ""
            try:
                newpath = map_url(user,args)
            except Exception,e:
                logger.error('%s' % e)
                
            self.synclock.acquire()
            vproc = create(user, software, display, self.config, newpath)
            self.synclock.release()
            
            if vproc != None : vproc.run()
            
            #make sure that the process is running
            if vproc != None and vproc.state == 'running':
                #atomic operation of the vprocess management List
                self.synclock.acquire()
                if not self.userproc.has_key(user):
                    self.userproc[user] = []
                self.userproc[user].append(vproc)
                self.procmap[vproc.uuid] = vproc
                self.synclock.release()   
                return vproc.status()
            return {}
        except Exception, e:
            logger.error('createProcess:%s' % e)
            try:
                self.synclock.release()
            except:
                pass           
            return {}
        
    def killVProcessUUID(self, uuid):
        try:
            retproc = []
            self.synclock.acquire()
            vproc = self.procmap[uuid]
            if(vproc):
                vproc.kill()
                if(vproc.state == 'stopped'):
                    self.userproc[vproc.user].remove(vproc)
                    self.procmap.pop(uuid)
                    retproc.append(vproc)
            self.synclock.release()
            
            return map(str, retproc)   
        except Exception, e:
            logger.error('KillProcess(%s):%s' % (uuid, e))
            try:
                self.synclock.release()
            except:
                pass
            return []
    
    def killVProcess(self, pid):
        try:
            cond = lambda proc: proc.pid == int(pid)
            procs = [inner for outer in self.userproc.values() for inner in outer]
            
            for each in procs:
                logger.debug(each)
                
            ca = filter(cond, procs)   
            if len(ca) <= 0: return
            retproc = []
            for each in ca:
                try:
                    each.kill()
                except:
                    continue
                self.synclock.acquire()
                self.userproc[each.user].remove(each)
                self.synclock.release()
                retproc.append(each)
                
            return map(str, retproc)
        except Exception, e:
            logger.error('KillProcess:%s' % e)
            try:
                self.synclock.release()
            except:
                pass
            return []
        
    
    def cleanVProcess(self, user=None, app=None):
        try:
#            self.synclock.aquaire
            self.synclock.acquire()
            pack = {}
            for li in self.userproc.values():
                for each in li:
                    if each.union_point is None or len(each.union_point) <= 1: continue
                    if not pack.has_key(each.union_point):
                         pack[each.union_point] = [] 
                    pack[each.union_point].append(each)
                    
            for li in pack.values():
                if len(filter(lambda x:x.state in ('stopped', 'united'), li)) == len(li):
                    for each in li:
                        try:
                            try:
                                each.kill()
                            except: pass
                            self.userproc[each.user].remove(each)
                            each.clean()
                        except Exception, e:
                            logger("%s" % e)
                            
            self.synclock.release()
        except Exception, e:    
            logger.error('clean-vprocess:%s' % e)
    
    def queryVProcess(self, user, softname=None):
        try:
            retproc = []
            if self.userproc.has_key(user):
                cond = lambda x: x.software.name == softname or softname == None
                retproc = map(str, filter(cond, self.userproc[user]))
            return retproc                
        except Exception, e:
            return []
        
    def queryAllVProcess(self):
        try:
            retproc = map(str, reduce(lambda x, y: x + y, self.userproc.values()))
            return retproc
        except Exception, e:
            logger.error('queryAllProcess:%s' % e)
            return []  
        
    def setServerMonitor(self, mon):
        self.sermon = mon
        
    def poll(self):
        try:
            self.sermon.report()
        except Exception, e:
            logger.error('poll server state:%s' % e)
        return ""
      
